package main

//#include <stdlib.h>
//#include <stdint.h>
/*
typedef struct C_Test_Data {
   int Value;
} CData;

typedef struct C_Test_Info {
   int Value;
   char* Str;
   char* ProcessorAddr;
   char* ProcessorNetwork;
   char* VendorAddr;
   char* VendorNetwork;
   void* responsibilityPointer;
   CData* Data;
} CInfo;

typedef void* Cosmos_Handle;
typedef struct _CosmosResult
{
	int64_t Code;
	char* Message;
} Cosmos_Result;
typedef struct _Cosmos_CallContext
{
	Cosmos_Handle CallerHandle;
	Cosmos_Handle TargetHandle;
} Cosmos_CallContext;
typedef struct _Cosmos_DataFrame
{
	char* Data;
	int32_t DataSize;
} Cosmos_DataFrame;
typedef struct _Cosmos_NotifyRequest
{
	char* Topic;
	char* RoutingKey;
	char* Message;
} Cosmos_NotifyRequest;
typedef struct _Cosmos_InvokeRequest
{
	char* Method;
	char* Parameters;
} Cosmos_InvokeRequest;
typedef struct _Cosmos_InvokeResponse
{
	Cosmos_Result* Result;
	Cosmos_DataFrame* DataFrame;
} Cosmos_InvokeResponse;
typedef struct _Cosmos_SubscriptionDataFrame
{
	char* SubscriptionId;
	Cosmos_DataFrame* DataFrame;
} Cosmos_SubscriptionDataFrame;
typedef struct _Cosmos_SubscribeRequest
{
	char* Topic;
	char* Parameters;
} Cosmos_SubscribeRequest;
typedef struct _CosmosSubscription
{
	char* SubscriptionId;
} Cosmos_Subscription;
typedef struct _Cosmos_SubscribeResponse
{
	Cosmos_Result* Result;
	Cosmos_Subscription* Subscription;
} Cosmos_SubscribeResponse;


typedef Cosmos_Handle Cosmos_EvironmentHandle;
typedef struct _Cosmos_ClientParameters
{
    char* Id;
    char* Sku;
    char* Version;
    char* CosmosMainAppPath;
	int HighDpiMode;
} Cosmos_ClientParameters;
typedef struct _Cosmos_ProxyParameters
{
    void* todo;
} Cosmos_ProxyParameters;
typedef struct _Cosmos_VisualParameters
{
    char* GuiThemeFrameworks;
    char* GuiThemeColorScheme;

} Cosmos_VisualParameters;
typedef struct _Cosmos_DeveloperParameter
{
    char* RuntimeMode;
    char* GuiMode;
    char* CosmosExecutiveFile;
    char* AppProviderMode;
    char* AppProviderUrl;
    int Timeout;
} Cosmos_DeveloperParameter;
typedef struct _Cosmos_WebViewParameters
{
    char* CefDirectory;
    char* CefResourcesDirectory;
    char* CefLocaleDirectory;
    char* CefExtraParameters;
} Cosmos_WebViewParameters;
typedef struct _Cosmos_GlobalizationParameters
{
    char* RegionId;
    char* LanguageId;
    char* TimeZoneId;
    char* Currency;
} Cosmos_GlobalizationParameters;
typedef struct _Cosmos_EnvironmentCreationParameters
{
    Cosmos_ClientParameters* ClientParameters;
    Cosmos_ProxyParameters* ProxyParameters;
    Cosmos_WebViewParameters* WebViewParameters;
    Cosmos_DeveloperParameter* DeveloperParameter;
    Cosmos_GlobalizationParameters* GlobalizationParameters;
    Cosmos_VisualParameters* VisualParameters;
    void* Responsibility;
} Cosmos_EnvironmentCreationParameters;

typedef struct _Cosmos_Account
{
	char* AccountId;
} Cosmos_AccountParameters;
typedef struct _Cosmos_CookieParameters
{
	void* todo;
} Cosmos_CookieParameters;
typedef struct _Cosmos_SessionCreationParameters
{
	Cosmos_AccountParameters* AccountParameters;
	Cosmos_CookieParameters* CookieParameters;
} Cosmos_SessionCreationParameters;
typedef struct _Cosmos_Session
{
	Cosmos_Handle ClientHandle;
	Cosmos_Handle ServerHandle;
} Cosmos_Session;
typedef struct _Cosmos_SessionCreationResult
{
    Cosmos_Result* Result;
    Cosmos_Session* Session;
} Cosmos_SessionCreationResult;
*/
import (
	"C"
)
import (
	"context"
	"encoding/json"
	"fmt"
	"unsafe"

	"Cosmos.Communication/cmd/sdk"
	"Cosmos.Communication/internal/biz"
	"Cosmos.Communication/internal/service"
)

var (
	instance *sdk.Role
)

//export Cosmos_InitializeEnvironment
func Cosmos_InitializeEnvironment(callContext *C.Cosmos_CallContext, environmentCreationParameters *C.Cosmos_EnvironmentCreationParameters, evironmentEventHandler unsafe.Pointer) (result *C.Cosmos_Result) {

	var environment = &sdk.Cosmos_EnvironmentCreationParameters{
		Client: &sdk.Cosmos_ClientParameters{
			Id:                C.GoString(environmentCreationParameters.ClientParameters.Id),
			Sku:               C.GoString(environmentCreationParameters.ClientParameters.Sku),
			CosmosMainAppPath: C.GoString(environmentCreationParameters.ClientParameters.CosmosMainAppPath),
			HighDpiMode:       int(environmentCreationParameters.ClientParameters.HighDpiMode),
			//Token:             environmentCreationParameters.ClientParameters.Token,
		},
		Developer: &sdk.Cosmos_DeveloperParameter{
			AppProviderMode: C.GoString(environmentCreationParameters.DeveloperParameter.AppProviderMode),
			RuntimeMode:     C.GoString(environmentCreationParameters.DeveloperParameter.RuntimeMode),
			GuiMode:         C.GoString(environmentCreationParameters.DeveloperParameter.GuiMode),
		},
		WebView: &sdk.Cosmos_WebViewParameters{
			CefDirectory:          C.GoString(environmentCreationParameters.WebViewParameters.CefDirectory),
			CefResourcesDirectory: C.GoString(environmentCreationParameters.WebViewParameters.CefResourcesDirectory),
			CefLocaleDirectory:    C.GoString(environmentCreationParameters.WebViewParameters.CefLocaleDirectory),
		},
		Responsibility: environmentCreationParameters.Responsibility,
	}

	var cosmosResult = sdk.Cosmos_InitializeEnvironment(environment, evironmentEventHandler)
	result = (*C.Cosmos_Result)(C.malloc(C.sizeof_Cosmos_Result))
	result.Code = C.int64_t(cosmosResult.Code)
	result.Message = C.CString(cosmosResult.Message)

	return result
}

//export Cosmos_UninitializeEnvironment
func Cosmos_UninitializeEnvironment() (result *C.Cosmos_Result) {
	var cosmosResult = sdk.Cosmos_UninitializeEnvironment()
	result = (*C.Cosmos_Result)(C.malloc(C.sizeof_Cosmos_Result))
	result.Code = C.int64_t(cosmosResult.Code)
	result.Message = C.CString(cosmosResult.Message)
	return
}

func Cosmos_CreateSession(callContext *C.Cosmos_CallContext, sessionCreationParameters *C.Cosmos_SessionCreationParameters) (result *C.Cosmos_SessionCreationResult) {
	var cosmosResult = sdk.Cosmos_CreateSession(nil)

	result = (*C.Cosmos_SessionCreationResult)(C.malloc(C.sizeof_Cosmos_SessionCreationResult))

	var cosmos_result = (*C.Cosmos_Result)(C.malloc(C.sizeof_Cosmos_Result))
	cosmos_result.Code = C.int64_t(cosmosResult.Code)
	cosmos_result.Message = C.CString(cosmosResult.Message)
	result.Result = cosmos_result

	if cosmosResult.Data != nil {
		var cosmos_session = (*C.Cosmos_Session)(C.malloc(C.sizeof_Cosmos_Session))
		cosmos_session.ClientHandle = (C.Cosmos_Handle)(unsafe.Pointer(uintptr(cosmosResult.Data.ClientHandle)))
		cosmos_session.ServerHandle = (C.Cosmos_Handle)(unsafe.Pointer(uintptr(cosmosResult.Data.ServerHandle)))
		result.Session = cosmos_session
	}

	return
}

//export Cosmos_Notify
func Cosmos_Notify(callContext *C.Cosmos_CallContext, notifyRequest *C.Cosmos_NotifyRequest) (result *C.Cosmos_Result) {
	result = (*C.Cosmos_Result)(C.malloc(C.sizeof_Cosmos_Result))
	if notifyRequest == nil {
		result.Code = C.int64_t(400)
		result.Message = C.CString("notifyRequest is nil")
		return
	}

	var meta = &biz.Meta{}
	var request = &biz.NotifyRequest{}
	if notifyRequest.Message != nil {
		request.Message = C.GoString(notifyRequest.Message)
	}
	if notifyRequest.Topic != nil {
		request.Topic = C.GoString(notifyRequest.Topic)
	}
	if notifyRequest.RoutingKey != nil {
		request.RoutingKey = C.GoString(notifyRequest.RoutingKey)
	}
	var cosmosResult = sdk.Cosmos_Notify(meta, request)
	result.Code = C.int64_t(cosmosResult.Code)
	result.Message = C.CString(cosmosResult.Message)
	return
}

//export Cosmos_Invoke
func Cosmos_Invoke(callContext *C.Cosmos_CallContext, invokeRequest *C.Cosmos_InvokeRequest) (response *C.Cosmos_InvokeResponse) {
	var result = (*C.Cosmos_Result)(C.malloc(C.sizeof_Cosmos_Result))
	response = (*C.Cosmos_InvokeResponse)(C.malloc(C.sizeof_Cosmos_InvokeResponse))
	response.Result = result
	if invokeRequest == nil {
		result.Code = C.int64_t(400)
		result.Message = C.CString("Cosmos_Invoke request is nil")
		return
	}

	var meta = &biz.Meta{}
	var request = &biz.InvokeRequest{}
	if invokeRequest.Method != nil {
		request.Function = C.GoString(invokeRequest.Method)
	}
	if invokeRequest.Parameters != nil {
		request.Parameters = C.GoString(invokeRequest.Parameters)
	}
	var invokeResponse = sdk.Cosmos_Invoke(meta, request)
	result.Code = C.int64_t(invokeResponse.Code)
	result.Message = C.CString(invokeResponse.Message)

	var dataFrame = (*C.Cosmos_DataFrame)(C.malloc(C.sizeof_Cosmos_DataFrame))
	response.DataFrame = dataFrame
	if invokeResponse.Data != nil {
		dataFrame.Data = C.CString(invokeResponse.Data.Value)
	} else {
		dataFrame.Data = C.CString("")
	}
	return
}

//export Cosmos_ReleaseInvokeResponse
func Cosmos_ReleaseInvokeResponse(callContext *C.Cosmos_CallContext, invokeResponse unsafe.Pointer) {
	/*C.free(unsafe.Pointer(invokeResponse.Result.Message))
	C.free(unsafe.Pointer(invokeResponse.Result))

	C.free(unsafe.Pointer(invokeResponse.DataFrame.Data))
	C.free(unsafe.Pointer(invokeResponse.DataFrame))

	C.free(unsafe.Pointer(invokeResponse))*/
	service.CallCosmos_ReleaseInvokeResponseAgent(invokeResponse)
}

//export Cosmos_PushSubscriptionData
func Cosmos_PushSubscriptionData(callContext *C.Cosmos_CallContext, subscriptionDataFrame *C.Cosmos_SubscriptionDataFrame) (result *C.Cosmos_Result) {

	result = (*C.Cosmos_Result)(C.malloc(C.sizeof_Cosmos_Result))
	if subscriptionDataFrame == nil || subscriptionDataFrame.DataFrame == nil || subscriptionDataFrame.DataFrame.Data == nil || subscriptionDataFrame.SubscriptionId == nil {
		result.Code = C.int64_t(400)
		result.Message = C.CString("Cosmos_PushSubscriptionData request is nil")
		return
	}

	var meta = &biz.Meta{}
	var cosmosDataFrame = &biz.DataFrame{}
	cosmosDataFrame.Ids = []string{C.GoString(subscriptionDataFrame.SubscriptionId)}
	cosmosDataFrame.Value = C.GoString(subscriptionDataFrame.DataFrame.Data)
	var pushResult = sdk.Cosmos_PushSubscriptionData(meta, cosmosDataFrame)
	result.Code = C.int64_t(pushResult.Code)
	result.Message = C.CString(pushResult.Message)

	return
}

//export Cosmos_ReleaseResult
func Cosmos_ReleaseResult(callContext *C.Cosmos_CallContext, result unsafe.Pointer) {

	/*if result == nil {
		return
	}

	if result.Message != nil {
		C.free(unsafe.Pointer(result.Message))
	}*/
	service.CallCosmos_ReleaseResultAgent(result)
}

func Push(dataChar *C.char) {
	var (
		data    = biz.DataFrame{}
		dataStr = C.GoString(dataChar)
	)
	json.Unmarshal([]byte(dataStr), &data)
	if instance == nil {
		return
	}
	instance.Push(context.Background(), &data)
}

func StringToChar(origin string) (result *C.char) {
	return C.CString(origin)
}

func TestCreateCInfo() *C.CInfo {
	var pinfo = (*C.CInfo)(C.malloc(C.sizeof_CInfo))
	fmt.Println("CInfo Struct Length", C.sizeof_CInfo)
	pinfo.Value = C.int(2)
	pinfo.Str = C.CString("test_str")
	return pinfo
}

func TestDestroyCInfo(info *C.CInfo) {
	C.free(unsafe.Pointer(info.Str))
	C.free(unsafe.Pointer(info))
}

func main() {
	/*var environment = &sdk.Cosmos_EnvironmentCreationParameters{
		Client: &sdk.Cosmos_ClientParameters{
			CosmosMainAppPath: "D:/Code/VisualStudio/Cosmos/Source/Cosmos.MainApp/bin/x86/Debug/net7.0-windows/Cosmos.MainApp.exe",
		},
		Developer: &sdk.Cosmos_DeveloperParameter{
			AppProviderMode: "nuget",
			RuntimeMode:     "debug",
			GuiMode:         "show",
		},
		WebView: &sdk.Cosmos_WebViewParameters{
			CefDirectory:          "C:/iFinD/cef84",
			CefResourcesDirectory: "C:/iFinD/cef84",
			CefLocaleDirectory:    "C:/iFinD/cef84/locales",
		},
	}
	result := sdk.Cosmos_InitializeEnvironment(environment, nil)
	fmt.Printf(result.Message)

	time.Sleep(5 * time.Second)

	var meta = &biz.Meta{
		Caller: "test",
	}
	invokeResult := sdk.Cosmos_Invoke(meta, &biz.InvokeRequest{
		Function:   "CreateWidget",
		Parameters: "",
	})
	fmt.Printf(invokeResult.Message)

	notifyResult := sdk.Cosmos_Notify(meta, &biz.NotifyRequest{})
	fmt.Printf(notifyResult.Message)

	pushResult := sdk.Cosmos_PushSubscriptionData(meta, &biz.DataFrame{
		Ids:   []string{"1"},
		Value: "data",
	})
	fmt.Printf(pushResult.Message)
	select {}*/
}
